#include <sys/ptrace.h>
#include <sys/type.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <android/log.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>

#define TAG "ptrace"

// 调用函数声明
static void help(int arc, char *argv[]);

// 监控系统调用
static void monitor_syscall(pid_t pid);

// 获取监控进程系统调用编号
long get_syscall_no(int pid, struct pt_regs *regs);

void main(int argc, char *argv[])
{
    if (argc != 2)
    {
        help(argc, argv);
        return;
    }
    pid_t target_pid;
    int status;
    target_pid = atoi(argv[1]);
    if (target_pid < 0)
    {
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "invalid process pid");
        return;
    }
    if (0 != ptrace(PTRACE_ATTACH, target_pid, NULL, NULL))
    {
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "ptrace attach error:%s", strerror(errono));
        return;
    }
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "start monitor process:%d", target_pid);
    while (1)
    {
        // 直到有信号来到或子进程结束
        wait(&status);
        if (WIFEXITED(status))
        {
            break;
        }
        monitor_syscall(target_pid);
        ptrace(PTRACE_SYSCALL, target_pid, NULL, NULL);
    }
    ptrace(PTRACE_DETACH, target_pid, NULL, NULL);
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "monitor finished");
}


static long get_syscall_no(int pid, struct pt_regs *regs)
{
    long sys_no = 0;
    ptrace(PTRACE_GETREGS, pid, NULL, regs);
    sys_no = ptrace(PTRACE_PEEKTEXT, pid, (void*)(regs->ARM_pc - 4), NULL);
    if (sys_no == 0)
        return -1;
    else if (sys_no == 0xef000000)
    {
        sys_no = regs->ARM_r7;
    }
    else
    {
        if ((sys_no & 0x0ff00000) != 0x0f900000)
        {
            return -1;
        }
        sys_no &= 0x000fffff;
    }
    return sys_no;
}


static void monitor_syscall(pid_t pid)
{
    long sys_no = 0;
    struct pt_regs regs;
    sys_no = get_syscall_no(pid, &regs);
    if (sys_no <= 0)
    {
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "get syscall no error");
    }
    else if (sysno == __NR_ioctl)
    {
        // 处理监控的系统调用
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "monitor ioctl syscall");
    }
    else
    {
        // 其它
    }
}


static void help(int arc, char *argv[])
{
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "Please use :%s pid", argv[0]);
}



